/*
 * Copyright (c) zhg2yqq.com Corp.
 * All Rights Reserved.
 */
package com.zhg2yqq.wheels.security.handler;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;

import com.alibaba.fastjson2.JSON;
import com.zhg2yqq.wheels.common.dto.CurrentUserDTO;
import com.zhg2yqq.wheels.common.response.RestResponse;
import com.zhg2yqq.wheels.common.util.ServletUtils;
import com.zhg2yqq.wheels.security.ISecurityEventHook;
import com.zhg2yqq.wheels.security.constants.SecurityResponseCode;
import com.zhg2yqq.wheels.security.context.SecurityUserHolder;

/**
 * @author zhg2yqq, 2022年11月28日
 * @version zhg2yqq v1.0
 */
public class LoginUserAccessDeniedHandler implements AccessDeniedHandler {
    private Logger log = LoggerFactory.getLogger(LoginUserAccessDeniedHandler.class);
    private ISecurityEventHook eventHook;

    public LoginUserAccessDeniedHandler() {
        super();
    }

    public LoginUserAccessDeniedHandler(ISecurityEventHook eventHook) {
        super();
        this.eventHook = eventHook;
    }

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response,
                       AccessDeniedException accessDeniedException)
            throws IOException {
        CurrentUserDTO user = SecurityUserHolder.getUser();
        if (user != null) {
            log.warn("用户：{} 越权访问受保护资源[{}]，AccessDeniedException：{}", user.getUsername(),
                    request.getRequestURI(), accessDeniedException);
        }
        if (eventHook != null) {
            eventHook.accessDeniedEvent(user, request);
        }
        if (ServletUtils.isAjaxRequest(request)) {
            // 允许跨域
            response.setHeader("Access-Control-Allow-Origin", "*");
            // 允许自定义请求头token(允许head跨域)
            response.setHeader("Access-Control-Allow-Headers",
                    "token, Accept, Origin, X-Requested-With, Content-Type, Last-Modified");
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write(JSON.toJSONString(
                    RestResponse.fail(SecurityResponseCode.SECURITY_NO_AUTHENTICATION)));
        } else {
            log.error(accessDeniedException.getLocalizedMessage(), accessDeniedException);
            response.sendError(HttpStatus.FORBIDDEN.value(),
                    HttpStatus.FORBIDDEN.getReasonPhrase());
        }
    }
}
